use std::fmt;

use crate::index::error::IndexError;

use super::ContainerId;
pub type ContainerResult<T> = Result<T,ContainerError>;

#[derive(Debug)]
pub enum ContainerError {
    WriteLargeChunk(usize),
    NotEnoughSpace(usize),
    StoreOpen(std::io::Error),
    OnWrite(std::io::Error),
    OnRead(std::io::Error),
    ReadNone(ContainerId,usize),
    ChunkNotFound,
    SeekPosition(std::io::Error),
    Sample(IndexError),
}

impl fmt::Display for ContainerError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::WriteLargeChunk(len) => write!(f,"Error chunk size(0x{:0x}) is more than container size(0x{:0x})"
                                                        ,len,crate::constants::CONTAINER_SIZE),
            Self::NotEnoughSpace(space) => write!(f,"Error space of container is not enough for 0x{:0x}B",space),
            Self::StoreOpen(e) => write!(f,"Error container store open error:{}",e),
            Self::OnWrite(e) => write!(f,"Error container write error:{}",e),
            Self::OnRead(e) => write!(f,"Error container read error:{}",e),
            Self::SeekPosition(e) => write!(f,"Error container seek position {}",e),
            Self::ReadNone(id, position) => write!(f,"Error container {} read with none at 0x{:0x}",id,position),
            Self::ChunkNotFound => write!(f,"Error chunk not found in container"),
            Self::Sample(e) => write!(f,"sample::{}",e),
        }
    }
}

impl std::error::Error for ContainerError {}

impl From<std::io::Error> for ContainerError {
    fn from(value: std::io::Error) -> Self {
        Self::StoreOpen(value)
    }
}

impl From<IndexError> for ContainerError {
    fn from(value: IndexError) -> Self {
        Self::Sample(value)
    }
}

impl From<usize> for ContainerError {
    fn from(value: usize) -> Self {
        if value > super::CAP_INIT_SIZE {
            Self::WriteLargeChunk(value)
        } else {
            Self::NotEnoughSpace(value)
        }
    }
}

pub fn write_err_from(err:std::io::Error) -> ContainerError {
    ContainerError::OnWrite(err)
}

pub fn read_err_from(err:std::io::Error) -> ContainerError {
    ContainerError::OnRead(err)
}

pub fn seek_err_from(err:std::io::Error) -> ContainerError {
    ContainerError::SeekPosition(err)
}